package org.uiot.protocol.codec

import org.uiot.protocol.PacketTraits
import org.uiot.protocol.group.CachedSequence
import org.uiot.protocol.group.Subjection
import spock.lang.Specification

import java.text.SimpleDateFormat

class CachedSequenceSpec extends Specification {

    final static groovyLoader = new GroovyClassLoader()
    final static dateFormatter = new SimpleDateFormat("yyMMddHHmmss")

    void "Test sequence decoding/encoding"() {
        given:
        def cachedRules = [
                myNumber: new CachedRule(
                        code: "test", name: "编解码1字节的数字", endian: CodecTraits.ENDIAN.LITTLE, length: 1,
                        lengthUnit: CodecTraits.LengthUnit.Byte, type: CodecTraits.Type.Numeric,
                        encodingScript: null, decodingScript: null, placeholder: null),
                myString: new CachedRule(
                        code: "test", name: "编解码10字节的字符串", endian: CodecTraits.ENDIAN.LITTLE, length: 10,
                        lengthUnit: CodecTraits.LengthUnit.Byte, type: CodecTraits.Type.StringASCII,
                        encodingScript: null, decodingScript: null, placeholder: null),
                myDate  : new CachedRule(
                        code               : "date2", name: "编解码压缩BCD码格式的日期", endian: CodecTraits.ENDIAN.LITTLE, length: 6,
                        lengthUnit         : CodecTraits.LengthUnit.Byte, type: CodecTraits.Type.StringCompressedBCD,
                        encodingScript: "x.format('yyMMddHHmmss')",
                        decodingScript: "new java.text.SimpleDateFormat('yyMMddHHmmss').parse(x)",
                        placeholder        : null)
        ]
        def cachedSequences = [
                new CachedSequence(part: PacketTraits.Part.Header, parentType: Subjection.Packet, parentCode: 01, serialNo: 1, name: "数据封包标识", dataIdentifier: "myNumber", ruleCode: "myNumber"),
                new CachedSequence(part: PacketTraits.Part.Header, parentType: Subjection.Packet, parentCode: 01, serialNo: 3, name: "设备标识", dataIdentifier: "myString", ruleCode: "myString"),
                new CachedSequence(part: PacketTraits.Part.Header, parentType: Subjection.Packet, parentCode: 01, serialNo: 5, name: "封包日期", dataIdentifier: "myDate", ruleCode: "myDate")
        ]

        and:
        def bitSrc = new BitSource(testcase.tobeDecodedContents)
        def decodedContents = [:]

        and:
        def bytes4Encoding = new ByteArrayOutputStream()
        def bitOps4Encoding = new BitOutputStream(bytes4Encoding)

        when:
        cachedSequences.each { CachedSequence cachedSequence ->
            if (!cachedSequence.cachedRule) {
                cachedSequence.cachedRule = cachedRules[cachedSequence.ruleCode]
            }
            cachedSequence.encode(bitOps4Encoding, testcase.tobeEncodedContents)

            cachedSequence.decode(bitSrc, decodedContents)
        }
        bitOps4Encoding.close()

        then:
        bytes4Encoding.toByteArray() == testcase.tobeDecodedContents

        and:
        decodedContents.findAll {
            testcase.tobeEncodedContents[it.key] != it.value
        }.size() == 0

        where:
        testcase << [
                [tobeEncodedContents: [myNumber:1, myString: "marsdonne1", myDate: dateFormatter.parse("121011163849")], tobeDecodedContents: BytesUtils.convertHexStringToByteArray("016d617273646f6e6e6531121011163849")]
        ]
    }
}
